/* Filename: mysh.c
 * Description: 模拟shell
 * Last modified: humble 20200323 17:09
 */
#include <stdio.h>
#include <stdlib.h>
#include <glob.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#define DELIM " \t\n" // 每个字符都可以用作分割

typedef struct {
    glob_t globres;
}cmd_t;

static void usage(void);

static void prompt(void) { printf("mysh-0.1$ "); }

static void parse(char *line, cmd_t *cmdptr) {
    char *tok = NULL;
    int i = 0;
    while(1){
        //strtok(); or strsep(); //把字符串按照DELIM分隔符来切割，每调用一次就返回下一个切片
        tok = strsep(&line, DELIM);
        if(tok == NULL){ break; }
        if(tok[0] == '\0'){ continue; } // 若连续出现分隔符就会出现空的切片，判断并跳过
        // GLOB_NOCHECK: 没有匹配到pattern，就把本身保存到globres里
        // GLOB_APPEND*0为0，代表初次调用时是覆盖而不是APPEND
        glob(tok, GLOB_NOCHECK|(GLOB_APPEND*i), NULL, &cmdptr->globres);
        i = 1; // i为1代表不是初次调用glob了
    }
}

int main(int argc, char **argv) {
    if(argc != 1){ fprintf(stderr, "argc !=1"); usage(); exit(1); }

    char *bufptr = NULL;
    size_t bufsize = 0;
    cmd_t cmd;
    pid_t pid;
    while(1){
        prompt();
        if(0 > getline(&bufptr, &bufsize, stdin)){ perror("getline"); break; }

        parse(bufptr, &cmd);

        if(0){ /* 内部命令 <TODO> */ }
        else{
            pid = fork();
            if(pid < 0){ perror("fork()"); exit(1); }
            else if(pid == 0){ // 子进程
                execvp(cmd.globres.gl_pathv[0], cmd.globres.gl_pathv);
                perror("execvp");
                exit(1);
            }
            else{ wait(NULL); /* 父进程<TODO> need globfree? free(bufptr)??*/ }
        }
    }
    return 0;
}

static void usage(void) {
#define USAGE "Usage:\n\
  Helloworld\n"
    printf(USAGE);
}
